﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using BLL = KC.Business.Stockmaster;

namespace KC.Presentation.Stockmaster
{
	public partial class Form1 : Form
	{
		private List<Dictionary<string, dynamic>> ResultList = new List<Dictionary<string, dynamic>>();
		private List<double> LastTradeValues = new List<double>();
		private DateTime nextReset = DateTime.MinValue;
		private List<graph> graphs = new List<graph>();
		private NewMonitor monitor;
		List<string> tickersTracked = new List<string>();

		public Form1()
		{
			InitializeComponent();
		}

		private void btnCxl_Click(object sender, EventArgs e)
		{
			DialogResult = System.Windows.Forms.DialogResult.Cancel;
			Close();
		}

		private void btnOK_Click(object sender, EventArgs e)
		{
			if (string.IsNullOrEmpty(txtUsername.Text.Trim())) {
				MessageBox.Show("Please enter a valid username.");
				return; }
			if (string.IsNullOrEmpty(txtPassword.Text.Trim())) {
				MessageBox.Show("Please enter a valid password.");
				return; }

			panel1.Visible = false;
			label4.Visible = true;
			menuStrip1.Enabled = true;
			tUpdateCharts_Tick(null, null);
		}

		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			new About().ShowDialog();
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			menuStrip1.Enabled = false;

			webBrowser1.WebBrowserShortcutsEnabled = false;
			webBrowser1.ScriptErrorsSuppressed = true;
			webBrowser1.AllowWebBrowserDrop = false;
			webBrowser1.IsWebBrowserContextMenuEnabled = false;
			webBrowser1.ScrollBarsEnabled = false;

			try { webBrowser1.Navigate("http://www.kconnolly.net/blogmaster.aspx"); }
			catch { }
			tBrowser.Start();
		}

		private void tickerChartToolStripMenuItem_Click(object sender, EventArgs e)
		{
			question question = new question("Enter ticker name(s), separated by commas:", "Enter ticker name(s)");
			if (question.ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
				return;
			string ticker = question.result.ToUpper();
			if (string.IsNullOrEmpty(ticker)) {
				MessageBox.Show("Invalid ticker");
				return; }

			// Add graphs to list and open them
			try {
				foreach (String ticker2 in ((string)ticker).Split(',')) {
					if (tickersTracked.Count >= 20) {
						MessageBox.Show("This version only supports tracking up to 20 tickers at once.");
						break; }
					try {
						graph g = new graph(ticker2.Trim(), tUpdateCharts.Interval, txtUsername.Text, txtPassword.Text);
						g.Show();
						graphs.Add(g);

						if (!tickersTracked.Contains(ticker2.Trim()))
							tickersTracked.Add(ticker2.Trim()); }
					catch { MessageBox.Show("An error occurred with ticker " + ticker2); } }}
			catch (Exception ex) { MessageBox.Show("Error loading tickers: \n" + ex.Message); }
			if (!tickersTracked.Contains(txtUsername.Text.Trim().ToUpper()))
				tickersTracked.Add(txtUsername.Text.Trim().ToUpper());
		}

		private void timer1_Tick(object sender, EventArgs e)
		{
			try { webBrowser1.Navigate("http://www.kconnolly.net/blogmaster.aspx"); }
			catch { }
		}

		private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
		{
			// {"error":"User Has Exceeded Hourly Limit","meta":{"uri":"\/profile\/info","limit":150,"limit_type":"user","requests":150,"reset":582,"recorded":"2011-05-04 03:43:59"}}
			if (tickersTracked.Count == 0) {
				e.Cancel = true;
				return; }
			
			string strResult = BLL.JsonLookups.ProfileInfo(txtUsername.Text, txtPassword.Text, string.Join(",", tickersTracked.AsEnumerable()));
			if (strResult.Contains("User Has Exceeded Hourly Limit")) {
				if (nextReset > DateTime.Today)
					e.Result = new Exception("API Status: API limit exceeded. Next limit reset: " + nextReset.ToString("MM/dd/yy HH:mm:ss"));
				else
					e.Result = new Exception("API Status: API limit exceeded. Empire Avenue resets this flag once per hour.");
				return; }
			e.Result = BLL.JsonLookups.DeserializeJson(strResult);
		}

		private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			try {
				if (e == null || e.Result == null || e.Cancelled || e.Error != null)
					return; }
			catch { return; }

			if (e.Result.GetType() == typeof(Exception)) {
				label2.Text = ((Exception)e.Result).Message;
				return; }

			Dictionary<string, dynamic> result = (Dictionary<string, dynamic>)e.Result;
			ResultList.Add(result);

			for (int i = graphs.Count - 1; i >= 0; i--)
			{
				if (graphs[i] == null) {
					graphs.RemoveAt(i);
					continue; }
				foreach (Newtonsoft.Json.Linq.JObject item in result["data"])
					if (item["ticker"].ToString().ToUpper() == graphs[i].ticker.ToUpper()) {
						graphs[i].ResultList.Add(item);
						graphs[i].LastTradeValues.Add(double.Parse(item["last_trade"].ToString())); }
				graphs[i].nextReset = DateTime.Now.AddSeconds(int.Parse(((Newtonsoft.Json.Linq.JObject)result["meta"])["reset"].ToString()));
				graphs[i].RenderInfo();
				graphs[i].RenderGraph();
			}

		}

		private void tUpdateCharts_Tick(object sender, EventArgs e)
		{
			if (!bgwUpdateStocks.IsBusy)
				bgwUpdateStocks.RunWorkerAsync();
			if (!bgwBalance.IsBusy)
				bgwBalance.RunWorkerAsync();

			// Clear out bogus tickers
			for (int i=graphs.Count - 1; i > 0; i--)
				if (!graphs[i].Enabled) 
					try {
						graphs.RemoveAt(i);
						tickersTracked.Remove(graphs[i].ticker); }
					catch { }
			for (int i = tickersTracked.Count - 1; i > 0; i--)
				if (graphs.Where(g => g.ticker == tickersTracked[i]).Count() == 0)
					tickersTracked.RemoveAt(i);

			// Monitor maintenance
			if (monitor != null && !monitor.Enabled)
				monitor = null;

			// Open new graph for new autobuys
			// Must have a monitor object, autobuys to add, API limit 20 per call, user selected auto graph option
			if (monitor != null && monitor.AutoBuys != null && graphs.Count < 20 && monitor.cbAutoGraph.Checked)
			{
				foreach (KeyValuePair<string, int> key in monitor.AutoBuys)
				{
					if (tickersTracked.Contains(key.Key))
						continue;
					tickersTracked.Add(key.Key);
					graph g = new graph(key.Key, tUpdateCharts.Interval, txtUsername.Text, txtPassword.Text);
					graphs.Add(g);
					g.Show();
					if (graphs.Count >= 20)
						break;
				}
			}

			

		}

		private void lookupByPriceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			MessageBox.Show("Sorry, but this feature is awaiting a feature request on the EAv API. They currently offer no way to do this.");
			return;

			question ques = new question("Enter an approximate stock price to look up:", "Enter target stock price");
			if (DialogResult != System.Windows.Forms.DialogResult.OK)
				return;
			double targetPrice;
			if (!double.TryParse(ques.result, out targetPrice)) {
				MessageBox.Show("Please enter a valid number.");
				return; }

			// Look up stocks near that price, order by ratio descending.


		}

		private void newStockMonitorToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (monitor != null && !monitor.Enabled)
				monitor = null;

			if (monitor != null)
				monitor.Focus();
			else {
				monitor = new NewMonitor(txtUsername.Text, txtPassword.Text);
				monitor.Show(); }
		}

		private void hlMoney_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			System.Diagnostics.Process.Start(@"http://www.empireavenue.com/profile/money/");
		}

		private void bgwBalance_DoWork(object sender, DoWorkEventArgs e)
		{
			try {
				string str = BLL.JsonLookups.Balance(txtUsername.Text, txtPassword.Text);
				Dictionary<string, dynamic> result = BLL.JsonLookups.DeserializeJson(str);
				e.Cancel = false;
				e.Result = result; }
			catch (Exception ex) {
				e.Cancel = true;
				e.Result = ex; }
		}

		private void bgwBalance_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
		{
			try {
				if (e == null || e.Result == null || e.Cancelled || e.Error != null)
					return; }
			catch { return; }

			if (e.Result.GetType() == typeof(Exception)) {
				hlMoney.Text = "API Error";
				return; }

			Dictionary<string, dynamic> result = (Dictionary<string, dynamic>)e.Result;
			if (result.ContainsKey("error")) lblApiCallsLeft.Text = "0";
			else
			{
				hlMoney.Text = "$ " + double.Parse(result["data"][0]["balance"].ToString()).ToString("###,###,###,###.##");
				// limit, reset
				nextReset = DateTime.Now.AddSeconds(int.Parse(result["meta"]["reset"].ToString()));
				TimeSpan timeLeft = nextReset - DateTime.Now;
				lblApiReset.Text = timeLeft.Minutes.ToString() + "m, " + timeLeft.Seconds.ToString() + "s";
				int limit = int.Parse(result["meta"]["limit"].ToString()),
					requests = int.Parse(result["meta"]["requests"].ToString());
				lblApiCallsLeft.Text = (limit - requests).ToString() + " / " + limit.ToString();
					
			}
		}

		private void closeAllChartWindowsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			foreach (graph g in graphs)
				try { g.Close(); g.Dispose(); }
				catch { }
			tickersTracked.Clear();
		}

	}
}
